//
// SoapTrace.Net - A soap message monitoring utility. 
//
// Copyright (C) 2005 Matthew Ward
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// Matthew Ward (mrward@users.sourceforge.net)

using SoapTrace.Core.Communication;
using System;
using System.IO;
using System.Text;
using System.Xml;

namespace SoapTrace.Core.Diagnostics
{
	/// <summary>
	/// Log file for a soap message.
	/// </summary>
	public class SoapMessageLogFile
	{
		/// <summary>
		/// The date time format used in the log file.
		/// </summary>
		public static readonly string DateTimeFormat = "yyyy-MM-dd HH:mm:ss.ff";
		
		/// <summary>
		/// Name of the root element of the log file.
		/// </summary>
		private static readonly string RootElementName = "SoapMessage";
				
		/// <summary>
		/// Name of the filter element.
		/// </summary>
		private static readonly string FilterElementName = "Filter";

		/// <summary>
		/// Name of the remote server element.
		/// </summary>
		private static readonly string ServerElementName = "Server";
		
		/// <summary>
		/// Name of the remote server port element.
		/// </summary>
		private static readonly string PortElementName = "Port";
		
		/// <summary>
		/// Name of the time element.
		/// </summary>
		private static readonly string TimeElementName = "Time";		
		
		/// <summary>
		/// Name of the source element.
		/// </summary>
		private static readonly string SourceElementName = "Source";
		
		/// <summary>
		/// Name of the request element.
		/// </summary>
		private static readonly string RequestElementName = "Request";		

		/// <summary>
		/// Name of the response element.
		/// </summary>
		private static readonly string ResponseElementName = "Response";
		
		/// <summary>
		/// Name of the header element.
		/// </summary>
		private static readonly string HeaderElementName = "Header";		
		
		/// <summary>
		/// Name of the soap message element.
		/// </summary>
		private static readonly string MessageElementName = "Message";
		
		/// <summary>
		/// Creates a new instance of the <see cref="SoapMessageLogFile"/>.
		/// </summary>
		private SoapMessageLogFile( )
		{
		}
		
		/// <summary>
		/// Saves the log file.
		/// </summary>
		/// <param name="filename">The log file name.</param>
		/// <param name="serverAddressFilter">The remote server being
		/// filtered on.</param>
		/// <param name="serverPortFilter">The remote server's port
		/// being filtered on.</param>
		/// <param name="requestAndResponse">The soap request
		/// and response.</param>
		public static void Save( string filename,
			string serverAddressFilter,
			int serverPortFilter, 
			SoapRequestAndResponse requestAndResponse ) 
		{
			StreamWriter Writer = new StreamWriter( filename, false, Encoding.UTF8 );
			
			Save( Writer, serverAddressFilter, serverPortFilter, requestAndResponse );
		}
		
		/// <summary>
		/// Saves the log file.
		/// </summary>
		/// <param name="writer">The log file writer.</param>
		/// <param name="serverAddressFilter">The remote server being
		/// filtered on.</param>
		/// <param name="serverPortFilter">The remote server's port
		/// being filtered on.</param>
		/// <param name="requestAndResponse">The soap request
		/// and response.</param>
		public static void Save( TextWriter writer,
			string serverAddressFilter,
			int serverPortFilter, 
			SoapRequestAndResponse requestAndResponse )
		{
			try
			{
				XmlTextWriter XmlTextWriter = new XmlTextWriter( writer );
				XmlTextWriter.Formatting = Formatting.Indented;
				
				XmlTextWriter.WriteStartElement( RootElementName );
				
				WriteTimeElement( XmlTextWriter, requestAndResponse.TimeReceived );
				WriteFilterElement( XmlTextWriter, serverAddressFilter, serverPortFilter );
				WriteSourceElement( XmlTextWriter, requestAndResponse.Source );
	
				WriteSoapMessageElement( XmlTextWriter, RequestElementName, requestAndResponse.Request );
				WriteSoapMessageElement( XmlTextWriter, ResponseElementName, requestAndResponse.Response );
				
				XmlTextWriter.WriteEndElement( );
			}
			finally
			{
				writer.Close( );
			}
		}
		
		/// <summary>
		/// Creates the filter element.
		/// </summary>
		/// <param name="writer">The xml text writer.</param>
		/// <param name="server">The remote server's name or IP
		/// address.</param>
		/// <param name="port">The remote server's port.</param>
		private static void WriteFilterElement( XmlTextWriter writer, string server, int port )
		{
			writer.WriteStartElement( FilterElementName );
			writer.WriteElementString( ServerElementName, server );
			writer.WriteElementString( PortElementName, port.ToString( ) );
			writer.WriteEndElement( );
		}
		
		/// <summary>
		/// Creates the time element.
		/// </summary>
		/// <param name="writer">The xml text writer to use.</param>
		/// <param name="time">The time.</param>
		private static void WriteTimeElement( XmlTextWriter writer, DateTime time )
		{
			writer.WriteElementString( TimeElementName, time.ToString( DateTimeFormat ) );
		}
		
		/// <summary>
		/// Creates the source element.
		/// </summary>
		/// <param name="writer">The xml text writer to use.</param>
		/// <param name="source">The source.</param>
		private static void WriteSourceElement( XmlTextWriter writer, string source )
		{
			writer.WriteElementString( SourceElementName, source );
		}	
		
		/// <summary>
		/// Creates the request or response element.
		/// </summary>
		/// <param name="writer">The xml text writer to use.</param>
		/// <param name="elementName">The element name.</param>
		/// <param name="message">The request or response.</param>
		private static void WriteSoapMessageElement( XmlTextWriter writer, string elementName, SoapMessage message )
		{
			writer.WriteStartElement( elementName );
			
			WriteTimeElement( writer, message.TimeReceived );
			
			WriteHeaderElement( writer, message.Header );
			WriteMessageElement( writer, message.Message );
			
			writer.WriteEndElement( );
		}	
		
		/// <summary>
		/// Creates the header element.
		/// </summary>
		/// <param name="writer">The xml text writer to use.</param>
		/// <param name="header">The header.</param>
		private static void WriteHeaderElement( XmlTextWriter writer, string header )
		{
			writer.WriteStartElement( HeaderElementName );
			writer.WriteCData( header );
			writer.WriteEndElement( );
		}		
		
		/// <summary>
		/// Creates the soap message element.
		/// </summary>
		/// <param name="writer">The xml text writer to use.</param>
		/// <param name="message">The soap message header.</param>
		private static void WriteMessageElement( XmlTextWriter writer, string message )
		{
			writer.WriteStartElement( MessageElementName );
			writer.WriteCData( message );
			writer.WriteEndElement( );
		}			
	}
}
